#pragma once

#include <queue>
#include <mutex>
#include <memory>
#include <functional>

namespace network {

    enum class EventType : unsigned char {
        Read = 1 << 0, // 00000001 读事件
        Write = 1 << 1, // 00000010 写事件
        Close = 1 << 2 // 00000100 关闭事件
    };

    enum class EventStatus : unsigned char {
        Ready, // 准备状态
        Active // 激活状态
    };

    // 事件队列顺序自定义比较器
    struct EventComparator {
        bool operator()(const EventType &a, const EventType &b) const {
            if (a == EventType::Write) {
                return false; // IOWrite 总是最小的
            }
            if (b == EventType::Write) {
                return true; // 其他事件总是大于 IOWrite
            }
            return a < b; // 对于其他事件，按自然顺序比较
        }
    };

    EventType operator|(EventType lhs, EventType rhs);

    EventType operator&(EventType lhs, EventType rhs);

    EventType& operator|=(EventType &lhs, EventType rhs);

    EventType& operator&=(EventType &lhs, EventType rhs);

    /**
      * @brief  检测事件类型中是否包含指定的事件
      * @note   左值为待检测的事件，右值为要检测的事件
      * @param  events 待检测的事件
      * @param  event  要对比的事件
      * @retval 待检测的事件是否有要检测的事件
      */
    bool hasEvent(EventType events, EventType event);

    class Event {

    public:

        using Handler = std::function<void(int, EventType, void *)>;

        Event(int fd, Handler handler, void *context = nullptr);

        void setReady() { status_ = EventStatus::Ready; }

        void setActive() { status_ = EventStatus::Active; }

        bool isReady() const { return status_ == EventStatus::Ready; }

        bool isActive() const { return status_ == EventStatus::Active; }

        void addEvent(EventType type) { queue_.emplace(type); }

        void addEventLock(EventType type);

        int getFd() const { return fd_; }

        Handler getHandler() { return handler_; }

        void* getContext() const { return context_; }

        EventType front() { return queue_.top(); }

        EventType pop();

        EventType popLock();

        bool empty() const { return queue_.empty(); }

    private:

        int fd_;

        EventStatus status_;

        Handler handler_;

        void *context_;

        std::mutex mutex_;

        std::priority_queue<EventType, std::vector<EventType>, EventComparator> queue_;

    };

    EventType operator|(EventType lhs, EventType rhs) {
        return static_cast<EventType>(static_cast<unsigned char>(lhs) | static_cast<unsigned char>(rhs));
    }

    EventType operator&(EventType lhs, EventType rhs) {
        return static_cast<EventType>(static_cast<unsigned char>(lhs) & static_cast<unsigned char>(rhs));
    }

    EventType& operator|=(EventType &lhs, EventType rhs) {
        lhs = lhs | rhs;
        return lhs;
    }

    EventType& operator&=(EventType &lhs, EventType rhs) {
        lhs = lhs & rhs;
        return lhs;
    }

    bool hasEvent(EventType events, EventType event) {
        return (events & event) == event;
    }

    Event::Event(int fd, Event::Handler handler, void *context) :
        fd_(fd),
        handler_(std::move(handler)),
        status_(EventStatus::Ready),
        context_(context) {}

    EventType Event::pop() {
        EventType type = queue_.top();
        queue_.pop();
        return type;
    }

    void Event::addEventLock(EventType type) {
        std::lock_guard<std::mutex> lock(mutex_);
        queue_.emplace(type);
    }

    EventType Event::popLock() {
        std::lock_guard<std::mutex> lock(mutex_);
        EventType type = queue_.top();
        queue_.pop();
        return type;
    }

}